package com.blue.http.websocket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.TaskExecutor;

import com.alibaba.fastjson.JSON;
import com.blue.core.dict.PushType;
import com.blue.core.util.JsonUtil;
import com.blue.http.annotation.WebsocketParser;
import com.blue.http.message.WebsocketRequest;
import com.blue.http.message.WebsocketResponse;
import com.blue.http.util.WebsocketException;
import com.blue.http.util.WebsocketUtil;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

/**
 * Websocket处理器
 * 
 * @author zhengj
 * @since 1.0 2016年12月15日
 */
public class WebsocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>
{
	private static Logger logger = LoggerFactory.getLogger(WebsocketServerHandler.class);

	private final TaskExecutor taskExecutor;
	private final WebsocketParser parser;
	private final WebsocketRouter router;

	public WebsocketServerHandler(TaskExecutor taskExecutor, WebsocketParser parser, WebsocketRouter router)
	{
		this.taskExecutor = taskExecutor;
		this.parser = parser;
		this.router = router;
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) throws Exception
	{
		Channel ch = ctx.channel();
		//ChannelId id = ch.id();
		String text = frame.text();
		logger.info("收到信息：{}", text);
		WebsocketRequest request = JSON.parseObject(text, WebsocketRequest.class);
		
		if (request.getType() == PushType.BROADCAST) // 广播通道注册
		{
			router.addBrodercast(request.getUrl(), ch);
		}
		else if (request.getType() == PushType.POINT) // 点对点通道注册
		{
			router.addPoint(request.getUrl(), request.getAccountId(), ch);
		}
		
		taskExecutor.execute(() ->
		{
			WebsocketResponse response = null;
			long start = System.currentTimeMillis();
			try
			{
				Object result = parser.invoke(request.getUrl(), text);
				if (result instanceof WebsocketResponse)
				{
					response = (WebsocketResponse)result;
				}
				else
				{
					response = WebsocketUtil.createResponse(request, WebsocketResponse.class);
					response.setResult(result);
				}
				WebsocketUtil.log(request, response, start, null);
			}
			catch (WebsocketException e)
			{
				if (response == null)
					response = WebsocketUtil.createResponse(request, WebsocketResponse.class);
					
				response.setState(false);
				response.setReason(e.getMessage());
				WebsocketUtil.log(request, response, start, e);
			}
			catch (Exception e)
			{
				if (response == null)
					response = WebsocketUtil.createResponse(request, WebsocketResponse.class);
					
				response.setState(false);
				response.setReason("系统错误");
				WebsocketUtil.log(request, response, start, e);
			}
			ch.writeAndFlush(new TextWebSocketFrame(JsonUtil.encode(response)));
		});
	}

	/*@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception
	{
		super.channelActive(ctx);
		Channel ch = ctx.channel();
		ChannelId id = ch.id();
		logger.info("客户端连接：{}，id={}", ch.remoteAddress(), id);
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception
	{
		super.channelInactive(ctx);
		Channel ch = ctx.channel();
		ChannelId id = ch.id();
		router.deletePoint(ch);
		logger.info("客户端断开连接：{}，id={}", ch.remoteAddress(), id);
	}*/

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
	{
		super.exceptionCaught(ctx, cause);
		Channel ch = ctx.channel();
		ChannelId id = ch.id();
		logger.error("客户端发生错误，断开连接：{}" + ch.remoteAddress() + "，id=" + id, cause);
		ch.close();
	}

}
